import { ECarDir, ECarState, ICarData, IStopPark } from "./Const";
import GameUI from "./GameUI";

const MAX: number[] = [4, 6, 8];
const OFFSET: number[] = [0, 20, 10, 20];

const { ccclass, property } = cc._decorator;

@ccclass
export default class BaseCar extends cc.Component {

    @property({ type: cc.SpriteAtlas, tooltip: "车图集" })
    private atlas: cc.SpriteAtlas = null;

    @property({ type: cc.Sprite, tooltip: "车阴影" })
    private shadow: cc.Sprite = null;

    @property({ type: cc.Sprite, tooltip: "车图片" })
    private sprite: cc.Sprite = null;

    @property({ type: cc.Node, tooltip: "箭头" })
    private arraw: cc.Node = null;

    @property({ type: cc.Label, tooltip: "0/4" })
    private lab: cc.Label = null;

    private ske: cc.Node = null;

    private isClicked: boolean = false;

    @property({
        tooltip: "颜色、大小、方向", visible() {
            this.updateCar();
            return true;
        }
    })
    private _data: cc.Vec3 = new cc.Vec3(0, 0, 0);
    public get data() {
        return this._data;
    }

    private _park: IStopPark = null;
    public get park() {
        return this._park;
    }

    private _carData: ICarData = null;
    public get carData() {
        return this._carData;
    }

    protected onLoad() {
        this.arraw.active = false;
        this.lab.node.active = false;
        this.setData(this._data);
    }

    /**
     * 刷新小车
     * @param data 颜色、大小、方向
     */
    public setData(data: cc.Vec3) {
        this._data = data;
        this._carData = {
            color: this._data.x,
            type: this._data.y,
            dir: this._data.z,
            cur: 0,
            max: MAX[this._data.y],
            state: this._carData?.state || ECarState.Click,
        };
        this.updateCar();
        this.updateValue();
    }

    public setState(state: ECarState) {
        this._carData.state = state;
        // console.log("set:", this._carData.state, state);
    }

    public get state() {
        // console.log("get:", this._carData.state);
        return this._carData.state;
    }

    public setDir(dir: ECarDir) {
        this._data.z = dir;
        this.setData(this._data);
        this.updateCar();
    }

    private createTuoWei() {
        const tuowei = cc.instantiate(GameUI.instance.tuowei);
        tuowei.parent = this.node;
        tuowei.active = true;
        tuowei.setPosition(0, 0);
        tuowei.setSiblingIndex(0);
    }

    private createSpine() {
        if (!this.ske) {
            this.ske = cc.instantiate(GameUI.instance.pengzhuang);
            this.ske.parent = this.node;
        }
        this.ske.active = true;
        this.ske.setPosition(0, 0);
        // this.ske.setSiblingIndex(0);
        const ske = this.ske.getComponent(sp.Skeleton);
        ske.setAnimation(0, "animation", false);
        ske.setCompleteListener((trackEntry) => {
            if (trackEntry.animation.name === "animation") {
                this.ske.active = false;
            }
        });


        this.ske.scale = 0.5;
        switch (this._carData.dir) {
            case ECarDir.Up:
                {
                    this.ske.angle = 0;
                    this.ske.setPosition(cc.v2(0, this.node.height / 2 - 10));
                }
                break;
            case ECarDir.Down:
                {
                    this.ske.angle = 0;
                    this.ske.setPosition(cc.v2(0, -this.node.height / 2 - 10));
                }
                break;
            case ECarDir.Left:
                {
                    this.ske.angle = 90;
                    this.ske.setPosition(cc.v2(-this.node.width / 2 + 10, 0));
                }
                break;
            case ECarDir.Right:
                {
                    this.ske.angle = 90;
                    this.ske.setPosition(cc.v2(this.node.width / 2 + 10, 0));
                }
                break;
        }
    }

    private updateCar() {
        const color = this._data.x;
        const type = this._data.y;
        const dir = this._data.z === 3 ? 1 : this._data.z;
        const url = `car${color + 1}_${dir}_${type}.`;
        this.shadow.spriteFrame = this.atlas.getSpriteFrame(url);
        this.sprite.spriteFrame = this.atlas.getSpriteFrame(url);
        this.shadow.node.scaleX = this._data.z === 3 ? -1 : 1;
        this.sprite.node.scaleX = this._data.z === 3 ? -1 : 1;
        this.node.width = this.sprite.node.width;
        this.node.height = this.sprite.node.height;
        this.arraw.angle = this._data.z * 90;
        this.sprite.node.setPosition(0, 0);
        // console.log("小车尺寸:", this.node.width, this.node.height, url);
    }

    public updateValue() {
        this.lab.string = `${this._carData.cur}/${this._carData.max}`;
    }

    public isFull() {
        return this._carData.cur >= this._carData.max;
    }

    private isMove: boolean = false;
    private carCover(cover: cc.Node) {
        if (this.isMove) { return; }
        this.isMove = true;
        const offset = OFFSET[this._carData.dir];
        const record = cc.v2(this.node.x, this.node.y);
        switch (this._carData.dir) {
            case ECarDir.Up:
            case ECarDir.Down:
                {
                    const distance = Math.abs(this.node.y - cover.y) / 5000;
                    
                    const offsetY = this._carData.dir == ECarDir.Up ? (cover.y - cover.height + offset) : (cover.y + cover.height + offset);
                    this.node.stopAllActions();
                    cc.tween(this.node).sequence(
                        cc.moveTo(distance, cc.v2(this.node.x, offsetY)),
                        cc.callFunc(() => {
                            // 碰撞特效、音效
                            this.createSpine();
                        }),
                        cc.delayTime(0.15),
                        cc.moveTo(distance, cc.v2(this.node.x, record.y)),
                        cc.callFunc(() => {
                            this.isMove = false;
                        }),
                    ).start();
                }
                break;
            case ECarDir.Left:
            case ECarDir.Right:
                {
                    const distance = Math.abs(this.node.x - cover.x) / 5000;
                    const offsetX = this._carData.dir == ECarDir.Right ? (cover.x - cover.width + offset) : (cover.x + cover.width + offset);
                    this.node.stopAllActions();
                    cc.tween(this.node).sequence(
                        cc.moveTo(distance, cc.v2(offsetX, this.node.y)),
                        cc.callFunc(() => {
                            // 碰撞特效、音效
                            this.createSpine();
                        }),
                        cc.delayTime(0.15),
                        cc.moveTo(distance, cc.v2(record.x, this.node.y)),
                        cc.callFunc(() => {
                            this.isMove = false;
                        }),
                    ).start();
                }
                break;
        }
    }

    public onCarClicked() {
        if (this._carData.state !== ECarState.Click) {
            return;
        }

        this._park = GameUI.instance.getStopPark();
        if (!this._park) {
            return;
        }

        const cover = GameUI.instance.getIsCover(this.node, this._carData.dir);
        if (cover) {
            this.carCover(cover);
            return;
        }


        if (this.isClicked) { return; }

        this.isClicked = true;
        setTimeout(() => {
            this.isClicked = false;
        }, 500);

        this._carData.state = ECarState.Go;
        this.createTuoWei();
        GameUI.instance.setParkDatas(this._park.index, this.node);
        GameUI.instance.gotoPark(this.node);
        // this._carData.dir = null;
        this.arraw.active = false;
        this.lab.node.active = false;
    }
}